package com.qixin.activiti.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qixin.activiti.service.IEaCommunicationsBXNCItfService;
import com.qixin.activiti.utils.EaListenerUtil;
import com.qixin.modules.ea.entity.EaBookDetail;
import com.qixin.modules.ea.entity.EaCommunications;
import com.qixin.modules.ea.service.IEaBookDetailService;
import com.qixin.modules.ea.service.IEaCommunicationsService;
import com.qixin.modules.log.entity.SysInterfaceLog;
import com.qixin.modules.rzInvoice.service.IEaBillService;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.nc.enums.WSEnum;
import org.jeecg.common.nc.service.NCWebService;
import org.jeecg.common.nc.vo.WSVO;
import org.jeecg.modules.activiti.entity.ActBusiness;
import org.jeecg.modules.activiti.entity.ActZTask;
import org.jeecg.modules.activiti.service.IActZTaskService;
import org.jeecg.modules.nc.service.INcBdPsnjobService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;


/***
 * @Description: 通讯费报销推送NC报销审核通过接口
 * @author: CYS
 * @date: 2022/3/15 10:16
 */
@Slf4j
@Service
public class EaCommunicationsBXNCItfServiceImpl implements IEaCommunicationsBXNCItfService {



    @Autowired
    private IEaCommunicationsService iEaCommunicationsService;
    @Autowired
    private IEaBookDetailService eaBookDetailService;
    @Autowired
    private IEaBillService iEaBillService;
    @Autowired
    private IActZTaskService iActZTaskService;
    @Autowired
    private INcBdPsnjobService iNcBdPsnjobService;

    @Value(value = "${qixin.ncserver.uri}")
    private  String nCUrl;
    /**
     * @Description: 设置表体
     * @author: CYS
     * @date: 2022/2/23 11:12
     * @param eaCommunications:
     * @param eaBookDetail:
     * @param detaijsonArray:
     * @param jsonArrayBody:
     * @Return: com.alibaba.fastjson.JSONObject
     */
    private  void bodySet(EaCommunications eaCommunications, EaBookDetail eaBookDetail, JSONArray detaijsonArray, JSONArray jsonArrayBody)throws Exception{
        for (int a=0;a<detaijsonArray.size();a++) {
            JSONObject jsonBody=new JSONObject();
            //发票明细行税率
            BigDecimal taxRate =detaijsonArray.getJSONObject(a).getBigDecimal("taxRate").divide(new BigDecimal("100"));            //发票明细行实际报销金额
            //发票明细行实际报销金额
            BigDecimal totalAmount=detaijsonArray.getJSONObject(a).getBigDecimal("totalAmount");
            //发票明细行实际报销金额对发票总金额占比
            BigDecimal moneyNProportion=totalAmount.divide(eaBookDetail.getAmount(),2, RoundingMode.HALF_UP);
            //发票实际报销金额
            BigDecimal actualEaAmt=eaBookDetail.getActualEaAmt().multiply(moneyNProportion);
            //税额
            BigDecimal tax = actualEaAmt.divide(taxRate.add(new BigDecimal("1")),2, RoundingMode.HALF_UP).multiply(taxRate);
            //无税金额
            BigDecimal taxless = actualEaAmt.subtract(tax);

            // 合计金额=实际报销金额
            jsonBody.put("amount",actualEaAmt);
            jsonBody.put("bbje",actualEaAmt);
            // 本币余额= -金额为0 否
            jsonBody.put("bbye", "0");
            // 冲借款本币金额= -金额为0 否
            jsonBody.put("cjkbbje", "0");
            // 冲借款原币金额= -金额为0 否
            jsonBody.put("cjkybje", "0");
            //发票类型
            jsonBody.put("defitem12", detaijsonArray.getJSONObject(a).getString("fpTypeName"));
            //不含税金额
            jsonBody.put("defitem13", taxless);
            jsonBody.put("defitem14", detaijsonArray.getJSONObject(a).getString("taxCode"));
            //税额
            jsonBody.put("defitem15", tax);
            if(eaBookDetail.getFygsr().equals(eaCommunications.getPersonId())){
                // 报销人部门=表体费用归属人部门
                jsonBody.put("deptid",eaCommunications.getDeptId());
            }else{
                jsonBody.put("deptid", iNcBdPsnjobService.getById(eaBookDetail.getPsnjobId()).getPkDept());
            }
            // 删除标志=0
            jsonBody.put("dr", "0");
            // 报销人单位 =表体费用归属人单位
            jsonBody.put("dwbm",eaCommunications.getCostCompCodeId());
            // 供应商=直接取表头收款人
            jsonBody.put("hbbm", eaCommunications.getRecPersonId());
            // 还款本币金额= -金额为0 否
            jsonBody.put("hkbbje", "0");
            // 还款原币金额= -金额为0
            jsonBody.put("hkybje", "0");
            // 报销人=报销人
            jsonBody.put("jkbxr", eaBookDetail.getFygsr());
            // 收款对象=收款对象-0=员工，1=供应商，2=客户，
            jsonBody.put("paytarget", "0");
            // 报销单业务行标识=子表主键
            jsonBody.put("pk_busitem", "");
            jsonBody.put("pk_jkbx", "");
            // 报销类型=消费类型-n
            jsonBody.put("pk_reimtype", eaBookDetail.getKind());
            // 收款人=收款人-收款对象为员工，收款人必填
            jsonBody.put("receiver",eaCommunications.getRecPersonId());
            // 行号=行号-n
            jsonBody.put("rowno", jsonArrayBody.size()+1);
            jsonBody.put("szxmid", eaCommunications.getIndexId());
            // 原币金额=实际付款金额
            jsonBody.put("ybje",actualEaAmt);
            // 支付本币金额 =实际报销金额
            jsonBody.put("zfbbje", actualEaAmt);
            // 支付原币金额=实际报销金额
            jsonBody.put("zfybje",  actualEaAmt);

            jsonArrayBody.add(jsonBody);
        }

    }



    @Override
    public SysInterfaceLog bXApprove(ActBusiness actBusiness, String billNo) throws Exception {
        SysInterfaceLog sysInterfaceLog = new SysInterfaceLog();
        sysInterfaceLog.setBusinessNo(billNo);


        //查询通讯报销头
        EaCommunications eaCommunications = iEaCommunicationsService.getById(actBusiness.getTableId());
        if (null == eaCommunications) {
            throw new RuntimeException("根据" + actBusiness.getTableId() + "TableId查询通讯报销空！");
        }
        EaListenerUtil.objectDefault(eaCommunications, EaCommunications.class);

        //查询通讯报销表体费用明细
        List<EaBookDetail> eaBookDetails = eaBookDetailService.selectByMainId(eaCommunications.getId());
        if (null == eaBookDetails || eaBookDetails.size() == 0) {
            throw new RuntimeException("根据" + eaCommunications.getId() + "TableId查询通讯报销费用明细集合为空！");
        }


        JSONObject jsonObject = new JSONObject();
        try {
                    /*
                    封装数据
                     */
            JSONObject jsonHead = new JSONObject();

            //根据表id查询任务记录最后审批人
            ActZTask actZTask = iActZTaskService.getActZTaskByTableId(actBusiness.getProcInstId());

            String userId = null;
            int i = 0;
            while (true){
                i++;
                userId = iActZTaskService.getActHiIdentitylinkById(actZTask.getProcInstId(), actZTask.getTaskId());

                if(StrUtil.isNotEmpty(userId) || i==100){
                    break;
                }
                Thread.sleep(3000);
            }
            if(StrUtil.isEmpty(userId)){
                throw new RuntimeException("根据表id查询任务记录最后审批人失败！");
            }

                    /*
                    表头封装
                     */
            // 报销本币金额=实际付款金额
            jsonHead.put("bbje", eaCommunications.getActualPayAmt());
            // 币种=人民币-币种主键，直接取人民币主键
            jsonHead.put("bzbm", "1002Z0100000000001K1");
            jsonHead.put("cjkbbje", "0");
            // 冲借款原币金额= -金额为0 否
            jsonHead.put("cjkybje", "0");
            // 创建人=创建人-用户主键
            jsonHead.put("creator", eaCommunications.getCreateBy());
            jsonHead.put("deptid", eaCommunications.getDeptId());
            // 报销人部门=报销人部门-组织_部门版本信息
            jsonHead.put("deptid_v", eaCommunications.getDeptId());
            // 单据编号=单据编号
            jsonHead.put("djbh", eaCommunications.getBillNo());
            // 单据大类=bx-bx
            jsonHead.put("djdl", "bx");
            // 单据类型编码=2643-通讯费:2643
            jsonHead.put("djlxbm", "2643");
            // 单据日期=单据日期-2021-12-15 09:32:43
            jsonHead.put("djrq", DateUtil.format(eaCommunications.getBillDate(), "yyyy-MM-dd HH:mm:ss"));
            // 单据状态=3-0=暂存，1=保存，2=审核，3=签字，-1=作废，
            jsonHead.put("djzt", eaCommunications.getState());
            // 原费用承担单位=费用承担单位-组织
            jsonHead.put("fydwbm", eaCommunications.getCostCompCodeId());
            // 费用承担单位=费用承担单位-组织_版本信息
            jsonHead.put("fydwbm_v", eaCommunications.getCostCompCodeId());
            jsonHead.put("dr", "0");
            // 本币汇率=默认为1
            jsonHead.put("bbhl", "1");
            jsonHead.put("dwbm", eaCommunications.getCompanyCodeId());
            // 报销人单位=报销人单位
            jsonHead.put("dwbm_v", eaCommunications.getCompanyCodeId());
            // 附件张数=附件张数 否
            jsonHead.put("fjzs", "0");
            // 原费用承担部门=费用承担部门-组织_部门
            jsonHead.put("fydeptid", eaCommunications.getCostDept());
            // 费用承担部门=费用承担部门-组织_部门版本信息
            jsonHead.put("fydeptid_v", eaCommunications.getCostDept());
            // 供应商=直接取表头收款人
            jsonHead.put("hbbm", eaCommunications.getRecPersonId());
            // 还款本币金额= -金额为0 否
            jsonHead.put("hkbbje", "0");
            jsonHead.put("hkybje", "0");
            // 报销人=报销人
            jsonHead.put("jkbxr", eaCommunications.getPersonId());
            // 结算方式=支付方式
            jsonHead.put("jsfs", eaCommunications.getPaymentMethod());
            // 签字日期=最后审 ， 核人审核日期
            jsonHead.put("jsr", actZTask.getOwnerId());
            // 会计年度=单据日期年度
            jsonHead.put("kjnd", "");
            // 会计期间=单据日期月份
            jsonHead.put("kjqj", "");
            // 录入人=录入人-用户主键
            jsonHead.put("operator", eaCommunications.getCreateBy());
            // 支付状态=3-3=支付完成
            jsonHead.put("payflag", "3");
            // 支付人=最后审批人(财务)
            jsonHead.put("payman", actZTask.getOwnerId());
            jsonHead.put("paytarget", "0");
            // pk_billtype=264X-264X
            jsonHead.put("pk_billtype", "264X");
            // 集团=集团
            jsonHead.put("pk_group", "0001A110000000000CLJ");
            // 财务组织=费用承担单位
            jsonHead.put("pk_fiorg", eaCommunications.getCostCompCodeId());
            // 报销单标识 =主表主键-n
            jsonHead.put("pk_jkbx", "");
            // 原报销单位=费用承担单位
            jsonHead.put("pk_org", eaCommunications.getCostCompCodeId());
            // 报销单位=费用承担单位
            jsonHead.put("pk_org_v", eaCommunications.getCostCompCodeId());
            // 原付款单位=费用承担单位
            jsonHead.put("pk_payorg", eaCommunications.getCostCompCodeId());
            // 付款单位=费用承担单位
            jsonHead.put("pk_payorg_v", eaCommunications.getCostCompCodeId());
            // 交易类型=NC交易类型主键
            jsonHead.put("pk_tradetypeid", "1001A11000000011GUC5");
            jsonHead.put("receiver", eaCommunications.getRecPersonId());
            // 审批状态=审批通过-0=审批未通过，1=审批通过，2=审批进行中，3=提交，-1=自由，
            jsonHead.put("spzt", "-1");
            // 生效标志=1-0=未生效，1=已生效，
            jsonHead.put("sxbz", "1");
            // 合计金额=实际付款金额
            jsonHead.put("total", eaCommunications.getActualPayAmt());
            // 原币金额=实际付款金额
            jsonHead.put("ybje", eaCommunications.getActualPayAmt());
            // 审批人=最后审批人(财务)-用户主键
            jsonHead.put("approver", actZTask.getOwnerId());
            // 支付本币金额 =实际付款金额
            jsonHead.put("zfbbje", eaCommunications.getActualPayAmt());
            jsonHead.put("zfybje", eaCommunications.getActualPayAmt());
            // 事由=事由
            jsonHead.put("zy", eaCommunications.getCause());
            // 收支项目=费用项目
            jsonHead.put("szxmid", eaCommunications.getIndexId());
            jsonHead.put("actionCode", "APPROVE" + userId);

            jsonObject.put("head", jsonHead);
                    /*
                    表头封装结束
                     */


                    /*
                    表体封装
                     */
            JSONArray jsonArrayBody = new JSONArray();
            for (int a = 0; a < eaBookDetails.size(); a++) {

                //获取费用明细
                EaBookDetail eaBookDetail = eaBookDetails.get(a);
                EaListenerUtil.objectDefault(eaBookDetail, EaBookDetail.class);

                List<Map<String, Object>> billDetailList = null;

                try {
                    //获取根据发票id获取发票明细集合
                    billDetailList = iEaBillService.getBillDetailList(eaBookDetail.getFpid());
                } catch (Exception e) {
                    throw new RuntimeException("获取发票明细失败!(StackTrace=" + EaListenerUtil.formatStackTrace(e) + ")");
                }

                //表体封装
                if (billDetailList != null || billDetailList.size() > 0) {
                    try {
                        JSONArray detaijsonObject = JSON.parseArray(JSON.toJSONString(billDetailList));
                        bodySet(eaCommunications, eaBookDetail, detaijsonObject, jsonArrayBody);
                    } catch (Exception e) {
                        throw new RuntimeException("fybx表体封装错误!(StackTrace=" + EaListenerUtil.formatStackTrace(e) + ")");
                    }
                } else {
                    throw new RuntimeException("获取发票明细空！");
                }


            }

            jsonObject.put("body", jsonArrayBody);
                    /*
                    表体封装结束
                     */

            //请求nc接口
            WSVO wsvo = NCWebService.sendToWS(nCUrl, WSEnum.COMMUNICATIONEXPENSEBX, jsonObject.toJSONString());

            //日志保存
            if(!wsvo.getStatus()){
                throw new RuntimeException(wsvo.getMessage());
            }
            sysInterfaceLog.setState("1");
            sysInterfaceLog.setDisposeState("0");
            sysInterfaceLog.setResult(wsvo.getMessage());
        } catch (Exception e) {
            sysInterfaceLog.setState("0");
            sysInterfaceLog.setDisposeState("1");
            sysInterfaceLog.setResult(e.getMessage());
        }
        sysInterfaceLog.setContent(jsonObject.toJSONString());
        sysInterfaceLog.setCreateTime(new DateTime());
        return sysInterfaceLog;
    }


}
